/*******************************************************************************
 * Copyright (c) 2005, 2014 springside.github.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 *******************************************************************************/
package com.sdgakj.service.account;

import com.alibaba.fastjson.JSONObject;
import com.sdgakj.entity.User;
import com.sdgakj.enums.EnumIsDelete;
import com.sdgakj.enums.EnumSMSType;
import com.sdgakj.enums.EnumUserType;
import com.sdgakj.repository.UserDao;
import com.sdgakj.service.ServiceException;
import com.sdgakj.service.account.ShiroDbRealm.ShiroUser;
import com.sdgakj.service.login.UserLoginService;
import com.sdgakj.utils.SMSSender;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springside.modules.security.utils.Digests;
import org.springside.modules.utils.Clock;
import org.springside.modules.utils.Encodes;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 用户管理类.
 * 
 * @author calvin
 */
// Spring Service Bean的标识.
@Component
@Transactional
public class AccountService
{
    
    public static final String HASH_ALGORITHM = "SHA-1";
    public static final int HASH_INTERATIONS = 1024;
    private static final int SALT_SIZE = 8;
    
    private static Logger logger = LoggerFactory.getLogger(AccountService.class);
    
    @Autowired
    private UserDao userDao;
    

    @Autowired
    private UserLoginService userLoginService;

    private Clock clock = Clock.DEFAULT;
    
    public List<User> getAllUser()
    {
        return (List<User>) userDao.findAll();
    }
    
    public User getUser(Long id)
    {
        return userDao.findOne(id);
    }
    
    public User findUserByLoginName(String loginName)
    {
        return userDao.findByLoginName(loginName);
    }
    
    /**
     * 根据用户名 查询管理员
     * 
     * @param loginName
     * @return
     */
    public User findAdminByLoginName(String loginName)
    {
        String type = "admin";
        String deltag = EnumIsDelete.NOTDELETE.getCode();
        return userDao.findAdminByLoginName(loginName, type, deltag);
    }
    
    /**
     * 录入数据人员
     * 
     * @param loginName
     * @return
     */
    public User findAdminNotUser(String loginName)
    {
        String type = "admin";
        String deltag = EnumIsDelete.NOTDELETE.getCode();
        return userDao.findAdminByLoginName(loginName, type, deltag);
    }
    /**
     * 注册普通用户带密码
     * 
     * @param user
     */
    public void registerUser(User user)
    {
        entryptPassword(user);
        user.setType(EnumUserType.CUSTOMOR.getCode()); // 标记是普通的用户类
        user.setRegisterDate(clock.getCurrentDate());

        userDao.save(user);
    }
    
    /**
     * 注册普通用户，不带密码的
     * 
     * @param user
     */
    public void registerUserNoPwd(User user)
    {
        user.setType(EnumUserType.CUSTOMOR.getCode()); // 标记是普通的用户类
        user.setRegisterDate(clock.getCurrentDate());
        
        userDao.save(user);
    }
    
    /**
     * 注册普通用户，不带密码的
     * 
     * @param user
     */
    public void registerUserPwd(User user)
    {
        entryptPassword(user);
        user.setType(EnumUserType.CUSTOMOR.getCode()); // 标记是普通的用户类
        user.setRegisterDate(clock.getCurrentDate());
        
        userDao.save(user);
    }
    
    public void updateUser(User user)
    {
        if(!StringUtils.isEmpty(user.getPlainPassword()))
        {
            entryptPassword(user);
        }
        userDao.save(user);
    }
    
    public void deleteUser(Long id)
    {
        if(isSupervisor(id))
        {
            logger.warn("操作员{}尝试删除超级管理员用户", getCurrentUserName());
            throw new ServiceException("不能删除超级管理员用户");
        }
        userDao.delete(id);
        
    }
    
    /**
     * 判断是否超级管理员.
     */
    private boolean isSupervisor(Long id)
    {
        return id == 1;
    }
    
    /**
     * 取出Shiro中的当前用户LoginName.
     */
    private String getCurrentUserName()
    {
        ShiroUser user = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
        return user.loginName;
    }
    
    /**
     * 设定安全的密码，生成随机的salt并经过1024次 sha-1 hash
     */
    public void entryptPassword(User user)
    {
        byte[] salt = Digests.generateSalt(SALT_SIZE);
        user.setSalt(Encodes.encodeHex(salt));
        
        byte[] hashPassword = Digests.sha1(user.getPlainPassword().getBytes(), salt, HASH_INTERATIONS);
        user.setPassword(Encodes.encodeHex(hashPassword));
    }

    /**
     * 判断密码是否一致，根据输入的密码和数据库的盐进行加密，比对数据库的密码
     * 
     * @param pwd
     * @return
     */
    public String getEntryptPassword(String pwd, String salt)
    {
        byte[] newSalt = Encodes.decodeHex(salt);
        byte[] hashPassword = Digests.sha1(pwd.getBytes(), newSalt, HASH_INTERATIONS);
        
        return Encodes.encodeHex(hashPassword);
    }
    
    /**
     * 生成6位数字的密码
     * 
     */
    public String getAutoPassword()
    {
        Random random = new Random();
        String sRand = "";
        for(int i = 0; i < 6; i++)
        {
            String rand = String.valueOf(random.nextInt(10));
            sRand += rand;
        }
        return sRand;
    }
    
    /**
     * 给用户手机号发送密码
     * 
     */
    public String sendSmsPassword(String tel, String password)
    {
        
        JSONObject json = new JSONObject();
        
        String content = "您的验证码是：" + password + "。请不要把验证码泄露给其他人。如非本人操作，可不用理会！（半小时内有效）";
        
        // RedisClient.cacheAdd(tel.concat("_code"), password, 30 * 60);
        
        // 发送短信
        String result = SMSSender.sendSms(tel, content, EnumSMSType.SECURITY_CODE);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("tel", tel);
        json.put("repBody", map);
        if(result != null && result.indexOf("<code>2") > -1)
        {
            json.put("resCode", "1");
            json.put("resMsg", "发送短信成功");
        }
        else
        {
            json.put("resCode", "0");
            json.put("resMsg", "发送短信失败");
        }
        return json.toJSONString();
    }
    
    @Autowired
    public void setUserDao(UserDao userDao)
    {
        this.userDao = userDao;
    }
    
    public void setClock(Clock clock)
    {
        this.clock = clock;
    }
}
